window.onload = function () {
  var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 1 });
  initSpread(spread);
  setOption(spread);
};

function initSpread(spread) {
  var lawOfUniversalGravitation = {
    richText: [
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: "F = (G * M"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "1"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: " * M"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "2"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: ") / R"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 1
        },
        text: "2"
      }
    ]
  };
  var reaction = {
    richText: [
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: "3 Ba(OH)"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "2"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: " + 2 H"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "3"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: "PO"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "4"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: " → 6 H"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "2"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: "O + Ba"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "3"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: "(PO"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "4"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: ")"
      },
      {
        style: {
          font: "normal 24px Calibri",
          vertAlign: 2
        },
        text: "2"
      },
      {
        style: {
          font: "normal 24px Calibri"
        },
        text: "↓"
      }
    ]
  };
  var google = {
    richText: [
      {
        style: {
          font: "bold 36px Calibri",
          foreColor: "rgb(78,133,242)"
        },
        text: "G"
      },
      {
        style: {
          font: "bold 36px Calibri",
          foreColor: "rgb(228,65,52)"
        },
        text: "o"
      },
      {
        style: {
          font: "bold 36px Calibri",
          foreColor: "rgb(247,188,32)"
        },
        text: "o"
      },
      {
        style: {
          font: "bold 36px Calibri",
          foreColor: "rgb(78,133,242)"
        },
        text: "g"
      },
      {
        style: {
          font: "bold 36px Calibri",
          foreColor: "rgb(65,168,87)"
        },
        text: "l"
      },
      {
        style: {
          font: "bold 36px Calibri",
          foreColor: "rgb(228,65,52)"
        },
        text: "e"
      }
    ]
  };
  var sheet = spread.sheets[0];
  sheet.suspendPaint();
  sheet.setColumnWidth(0, 720);
  sheet.setValue(0, 0, 'Law of universal gravitation:', 3);
  sheet.setValue(1, 0, lawOfUniversalGravitation, 3);
  sheet.setRowHeight(1, 40);
  sheet.getCell(1, 0).vAlign(GC.Spread.Sheets.VerticalAlign.center);
  sheet.setValue(3, 0, 'The reaction of barium hydroxide with phosphoric acid:', 3);
  sheet.setValue(4, 0, reaction, 3);
  sheet.setRowHeight(4, 40);
  sheet.getCell(4, 0).vAlign(GC.Spread.Sheets.VerticalAlign.center);
  sheet.setValue(6, 0, google, 3);
  sheet.setRowHeight(6, 50);
  sheet.name('Basic Usage');
  sheet.resumePaint();
  spread.options.tabStripRatio = 0.8;
}
function setOption(spread) {
  var _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];
      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }
    return target;
  };

  var addEventListener = function (parent, type, listener) {
    return parent.addEventListener(type, listener);
  };
  var appendChild = function (parent, child) {
    return parent.appendChild(child);
  };
  var createElement = function (tag) {
    return document.createElement(tag);
  };
  var queryCommandState = function (command) {
    return document.queryCommandState(command);
  };
  var queryCommandValue = function (command) {
    return document.queryCommandValue(command);
  };
  var defaultClasses = {
    actionbar: 'rich-editor-actionbar',
    button: 'rich-editor-button',
    content: 'rich-editor-content',
    selected: 'rich-editor-button-selected'
  };
  var defaultParagraphSeparatorString = 'defaultParagraphSeparator';
  var formatBlock = 'formatBlock';
  var exec = function (command) {
    var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
    return document.execCommand(command, false, value);
  };
  // font element limitation, only support font size from 1~7
  var convertFontSize = function (value) {
    if (value <= 10) {
      return 1;
    } else if (value <= 13) {
      return 2;
    } else if (value <= 16) {
      return 3;
    } else if (value <= 18) {
      return 4;
    } else if (value <= 24) {
      return 5;
    } else if (value <= 32) {
      return 6;
    } else {
      return 7;
    }
  };
  var fontSizeDict = [0, 10, 13, 16, 18, 24, 32, 48];

  var _stopBubble = function (e) {
    if (e && e.stopPropagation) {
      e.stopPropagation();
    } else {
      window.event.cancelBubble = true;
    }
  };
  var _colorRGB2Hex = function (color) {
    var rgb = color.split(',');
    var r = parseInt(rgb[0].split('(')[1]);
    var g = parseInt(rgb[1]);
    var b = parseInt(rgb[2].split(')')[0]);
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
  };
  var createRichTextElement = function (tag, value) {
    var elem;
    switch (tag) {
      case 'subscript':
        elem = createElement('sub');
        break;
      case 'superscript':
        elem = createElement('sup');
        break;
      case 'underline':
        elem = createElement('u');
        break;
      case 'strikeThrough':
        elem = createElement('strike');
        break;
      case 'foreColor':
        elem = createElement('font');
        elem.color = _colorRGB2Hex(value);
        break;
      case 'fontName':
        elem = createElement('font');
        elem.face = value;
        break;
      case 'fontSize':
        elem = createElement('font');
        elem.size = convertFontSize(value);
        break;
      case 'bold':
        elem = createElement('b');
        break;
      case 'italic':
        elem = createElement('i');
        break;
      default:
        elem = createElement('span');
        break;
    }
    return elem;
  };
  var addFonts = function (container) {
    var defaultFonts = {
      ff1: { name: "Arial", text: "Arial" },
      ff2: { name: "Arial Black", text: "Arial Black" },
      ff3: { name: "Calibri", text: "Calibri" },
      ff4: { name: "Cambria", text: "Cambria" },
      ff5: { name: "Candara", text: "Candara" },
      ff6: { name: "Century", text: "Century" },
      ff7: { name: "Courier New", text: "Courier New" },
      ff8: { name: "Comic Sans MS", text: "Comic Sans MS" },
      ff9: { name: "Garamond", text: "Garamond" },
      ff10: { name: "Georgia", text: "Georgia" },
      ff11: { name: "Malgun Gothic", text: "Malgun Gothic" },
      ff12: { name: "Mangal", text: "Mangal" },
      ff13: { name: "Meiryo", text: "Meiryo" },
      ff14: { name: "MS Gothic", text: "MS Gothic" },
      ff15: { name: "MS Mincho", text: "MS Mincho" },
      ff16: { name: "MS PGothic", text: "MS PGothic" },
      ff17: { name: "MS PMincho", text: "MS PMincho" },
      ff18: { name: "Tahoma", text: "Tahoma" },
      ff19: { name: "Times", text: "Times" },
      ff20: { name: "Times New Roman", text: "Times New Roman" },
      ff21: { name: "Trebuchet MS", text: "Trebuchet MS" },
      ff22: { name: "Verdana", text: "Verdana" },
      ff23: { name: "Wingdings", text: "Wingdings" }
    };
    var $ul = container;
    var fontItems = [];
    var prefix = 'ff', i = 1, id = prefix + i;
    while (defaultFonts[id]) {
      fontItems.push(('<li class="fontfamily-item">' +
        defaultFonts[id].name +
        '</li>'));
      // .replace(/\{id\}/g, id));
      i++;
      id = prefix + i;
    }
    $ul.append($(fontItems.join('')));
  };

  var defaultActions = {
    fontFamily: {
      icon: '<span id="fontFamilyValue">Calibri</span>' +
        '<span class="drop-down-arrow"></span>',
      title: 'Bold',
      type: 'drop-down',
      specialStyle: {
        width: '150px'
      },
      dropDownListId: 'fontFamilyList',
      queryValue: function () {
        var value = queryCommandValue('fontName').replace(/"/g, '');
        if (value.length > 15) { // if fontFamily string is too long,
          value = value.substring(0, 15) + '...';
        }
        document.getElementById('fontFamilyValue').innerText = value;
      },
      result: function (e) {
        e.currentTarget.style.display = 'none';
        _stopBubble(e);
        var result = e.target.nodeName.toUpperCase() === 'LI' ? e.target.innerText : null;
        if (result) {
          document.getElementById('fontFamilyValue').innerText = result;
          exec('fontName', result);
          return true;
        } else {
          return false;
        }
      }
    },
    fontSize: {
      icon: '<span id="fontSizeValue">13</span>' +
        '<span class="drop-down-arrow"></span>',
      title: 'Bold',
      type: 'drop-down',
      specialStyle: {
        width: '40px'
      },
      dropDownListId: 'fontSizeList',
      queryValue: function () {
        var fontSizeMap = [0, 10, 13, 16, 18, 24, 32, 48];
        var value = queryCommandValue('fontSize');
        document.getElementById('fontSizeValue').innerText = fontSizeMap[value] ? fontSizeMap[value] : document.getElementById('fontSizeValue').innerText;
      },
      result: function (e) {
        e.currentTarget.style.display = 'none';
        _stopBubble(e);
        var result = e.target.nodeName.toUpperCase() === 'LI' ? parseInt(e.target.value) : null;
        if (result !== null) {
          document.getElementById('fontSizeValue').innerText = fontSizeDict[result];
          exec('fontSize', result);
          return true;
        } else {
          return false;
        }
      }
    },
    bold: {
      icon: '<b>B</b>',
      title: 'Bold',
      state: function () {
        return queryCommandState('bold');
      },
      result: function () {
        return exec('bold');
      }
    },
    italic: {
      icon: '<i>I</i>',
      title: 'Italic',
      state: function () {
        return queryCommandState('italic');
      },
      result: function () {
        return exec('italic');
      }
    },
    underline: {
      icon: '<u>U</u>',
      title: 'Underline',
      state: function () {
        return queryCommandState('underline');
      },
      result: function () {
        return exec('underline');
      }
    },
    strikethrough: {
      icon: '<strike>S</strike>',
      title: 'Strike-through',
      state: function () {
        return queryCommandState('strikeThrough');
      },
      result: function () {
        return exec('strikeThrough');
      }
    },
    colorPicker: {
      icon: '<span id="foreColorValue" class="color_picker_result">&nbsp;A&nbsp;</span>' +
        '<span class="drop-down-arrow"></span>',
      title: 'colorPicker',
      type: 'drop-down',
      specialStyle: {
        width: '40px'
      },
      dropDownListId: 'colorPicker',
      queryValue: function () {
        var value = queryCommandValue('foreColor');
        document.getElementById('foreColorValue').style.borderBottomColor = value;
      },
      result: function result(e) {
        e.currentTarget.style.display = 'none';
        _stopBubble(e);
        return e.target.nodeName.toUpperCase() === 'LI' ? exec('foreColor', _colorRGB2Hex(e.target.style.backgroundColor)) : false;
      }
    },
    superScript: {
      icon: 'X<sup>2</sup>',
      title: 'SuperScript',
      state: function () {
        return queryCommandState('superscript');
      },
      result: function () {
        return exec('superscript');
      }
    },
    subScript: {
      icon: 'X<sub>2</sub>',
      title: 'SubScript',
      state: function () {
        return queryCommandState('subscript');
      },
      result: function () {
        return exec('subscript');
      }
    }
  };

  function _getRichText() {
    var iterator = document.createNodeIterator(document.getElementsByClassName('rich-editor-content')[0], NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, false);
    var root = iterator.nextNode();// root
    var richText = [];
    var style = {};
    var text = '';
    var node = iterator.nextNode();
    var underlineNode = null, lineThroughNode = null, pNode = null;
    while (node !== null) {
      if (node.nodeType === 3/*TextNode*/) {
        text = node.nodeValue;
        style = document.defaultView.getComputedStyle(node.parentElement, null);
        if (underlineNode && underlineNode.contains(node) === false) {
          underlineNode = null;
        }
        if (lineThroughNode && lineThroughNode.contains(node) === false) {
          lineThroughNode = null;
        }
        if (pNode && _getLastTextNode(pNode) === node && _getLastTextNode(root) !== node) {
          text = text + '\r\n';
          pNode = null;
        }
        var richTextStyle = _getRichStyle(style, underlineNode, lineThroughNode);
        _handleSuperAndSubScript(root, node, richTextStyle);
        richText.push({
          style: richTextStyle,
          text: text
        });
      } else if (node.nodeName.toLowerCase() === 'p') {
        pNode = node;
      } else if (node.nodeName.toLowerCase() === 'u') {
        underlineNode = node;
      } else if (node.nodeName.toLowerCase() === 'strike') {
        lineThroughNode = node;
      }

      node = iterator.nextNode();
    }
    return richText;
  };

  function _handleSuperAndSubScript(root, node, style) {
    if (root === node) {
      return;
    }
    while (node.parentNode !== root) {
      if (node.nodeName.toLowerCase() === 'sub') {
        style.vertAlign = 2;
        break;
      }
      if (node.nodeName.toLowerCase() === 'sup') {
        style.vertAlign = 1;
        break;
      }
      node = node.parentNode;
    }
  };

  function _getRichStyle(style, isUnderlineNode, isLineThroughNode) {// getComputedStyle can't get inherit textDecoration
    return {
      font: (style.fontWeight === '700' ? 'bold ' : '') + (style.fontStyle === 'italic' ? 'italic ' : '') + style.fontSize + ' ' + style.fontFamily,
      foreColor: style.color,
      textDecoration: (isUnderlineNode ? 1 : 0) | (isLineThroughNode ? 2 : 0)
    };
  };

  function _getLastTextNode(root) {
    if (root && root.nodeType === 1) {
      var child = root.lastChild;
      return _getLastTextNode(child);
    } else {
      return root;
    }
  };

  var _initContent = function (settings) {

    var actions = settings.actions ? settings.actions.map(function (action) {
      if (typeof action === 'string') {
        return defaultActions[action];
      }
      else if (defaultActions[action.name]) {  //NOSONAR
        return _extends({}, defaultActions[action.name], action);
      }
      return action;
    }) : Object.keys(defaultActions).map(function (action) {
      return defaultActions[action];
    });

    var classes = _extends({}, defaultClasses, settings.classes);

    var defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div';

    var actionbar = createElement('div');
    actionbar.className = classes.actionbar;
    appendChild(settings.element, actionbar);

    var content = settings.element.content = createElement('div');
    content.contentEditable = true;
    content.className = classes.content;

    content.oninput = function (_ref) {
      var firstChild = _ref.target.firstChild;
      if (firstChild && firstChild.nodeType === 3) {
        exec(formatBlock, '<' + defaultParagraphSeparator + '>');
      } else if (content.innerHTML === '<br>') {//NOSONAR
        content.innerHTML = '';
      }
    };
    content.onkeydown = function (event) {
      if (event.key === 'Tab') {
        event.preventDefault();
      } else if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
        setTimeout(function () {
          return exec(formatBlock, '<' + defaultParagraphSeparator + '>');
        }, 0);
      }
    };
    appendChild(settings.element, content);
    var contentWrapper = createElement(defaultParagraphSeparator);


    appendChild(content, contentWrapper);

    if (!this._addedFonts) {
      addFonts($("#fontFamilyList"));
      this._addedFonts = true;
    }

    actions.forEach(function (action) {
      var button = createElement('button');
      button.className = classes.button;
      button.innerHTML = action.icon;
      // button.title = action.title;


      if (action.specialStyle) {
        for (var styleProp in action.specialStyle) {
          if (action.specialStyle.hasOwnProperty(styleProp)) {
            button.style[styleProp] = action.specialStyle[styleProp];
          }
        }
      }


      button.setAttribute('type', 'button');
      button.onclick = function () {
        // should notify each action button to close its drop-down list.
        var lists = document.getElementsByClassName('list');
        var dropDownList = document.getElementById(action.dropDownListId);
        for (var k = 0; k < lists.length; k++) {
          if (lists[k] !== dropDownList) {
            lists[k].style.display = 'none';
          }
        }
        if (action.type === 'drop-down') {
          if (button.contains(dropDownList)) {
            dropDownList.style.display === 'none' ? (dropDownList.style.display = 'block') : (dropDownList.style.display = 'none'); //NOSONAR
          } else {
            var dropDownListClone = dropDownList.cloneNode(true);
            if (action.queryValue) {
              addEventListener(dropDownListClone, 'click', action.queryValue);
            }
            button.appendChild(dropDownListClone);
            var hostOffsetHeight = button.offsetHeight;
            dropDownListClone.style.top = hostOffsetHeight + 'px';
            dropDownListClone.style.display = 'block';
            dropDownListClone.onclick = function (e) {
              return action.result(e) && content.focus();
            };
          }
        } else if (action.type === 'designer-gcui-widget') {
          $(action.widgetId).toggle();
        } else {
          return action.result() && content.focus();
        }
      };

      var handler;

      if (action.state) {
        handler = function () {
          return button.classList[action.state() ? 'add' : 'remove'](classes.selected);
        };
        addEventListener(content, 'keyup', handler);
        addEventListener(content, 'mouseup', handler);
        addEventListener(button, 'click', handler);
      }

      if (action.queryValue) {
        handler = action.queryValue;
        addEventListener(content, 'keyup', handler);
        addEventListener(content, 'mouseup', handler);
        addEventListener(button, 'click', handler);
      }

      appendChild(actionbar, button);
    });

    if (settings.styleWithCSS) {
      exec('styleWithCSS');
    }
    exec(defaultParagraphSeparatorString, defaultParagraphSeparator);

    return settings.element;
  }
  var richEditor = { exec: exec, init: _initContent };
  spread.bind(GC.Spread.Sheets.Events.EnterCell, onSpreadEnterCell);
  function onSpreadEnterCell() {
    var sheet = spread.getActiveSheet();
    var contentWrapper = $('.rich-editor-content')[0];
    contentWrapper.innerHTML = "";
    var contentText = sheet.getValue(sheet.getActiveRowIndex(), sheet.getActiveColumnIndex(), 3/* sheetArea */, 1/* richText */);
    if (contentText && contentText.richText) {
      for (var i = 0; i < contentText.richText.length; i++) {
        var elemAttr = [];
        if (contentText.richText[i].style && contentText.richText[i].text) {
          for (var styleProperty in contentText.richText[i].style) {
            if (contentText.richText[i].style.hasOwnProperty(styleProperty)) {
              switch (styleProperty) {
                case 'vertAlign':
                  if (contentText.richText[i].style[styleProperty] === 2) {
                    elemAttr.push('subscript');
                  } else if (contentText.richText[i].style[styleProperty] === 1) {
                    elemAttr.push('superscript');
                  }
                  break;
                case 'textDecoration':
                  if ((contentText.richText[i].style[styleProperty] & 1) === 1) {
                    elemAttr.push('underline');
                  }
                  if ((contentText.richText[i].style[styleProperty] & 2) === 2) {
                    elemAttr.push('strikeThrough');
                  }
                  break;
                case 'foreColor':
                  elemAttr.push({
                    name: 'foreColor',
                    value: contentText.richText[i].style[styleProperty]
                  });
                  break;
                case 'font':
                  var spanElem = createElement('div');
                  spanElem.style.font = contentText.richText[i].style[styleProperty];
                  if (spanElem.style.fontFamily) {
                    elemAttr.push({
                      name: 'fontName',
                      value: spanElem.style.fontFamily
                    });
                  }
                  if (spanElem.style.fontSize) {
                    elemAttr.push({
                      name: 'fontSize',
                      value: parseInt(spanElem.style.fontSize)
                    });
                  }
                  if (spanElem.style.fontWeight === 'bold') {
                    elemAttr.push('bold');
                  }
                  if (spanElem.style.fontStyle === 'italic') {
                    elemAttr.push('italic');
                  }
                  break;
              }
            }
          }
        }
        var parentElem = contentWrapper;
        for (var j = 0; j < elemAttr.length; j++) {
          var richTextElem;
          if (typeof elemAttr[j] === 'string') {
            richTextElem = createRichTextElement(elemAttr[j]);
          } else if (typeof elemAttr[j] === 'object' && elemAttr[j]) {
            richTextElem = createRichTextElement(elemAttr[j].name, elemAttr[j].value);
          }
          console.log(parentElem, richEditor, 'parentElem')
          appendChild(parentElem, richTextElem);
          parentElem = richTextElem;
          if (j === elemAttr.length - 1 && richTextElem) {
            richTextElem.innerHTML = contentText.richText[i].text;
          }
        }
      }
    } else {
      contentWrapper.innerHTML = contentText;
    }
  }
  richEditor.init({
    element: document.getElementById('richEditor'),
    defaultParagraphSeparator: 'p',
    styleWithCSS: false,
  });
  $("#setRichText").click(function () {
    var spread = GC.Spread.Sheets.findControl("ss");
    var sheet = spread.getActiveSheet();
    var richText = _getRichText();
    if (richText.length > 0) {
      sheet.setValue(sheet.getActiveRowIndex(), sheet.getActiveColumnIndex(), {
        richText: richText
      });
    }
  });
}

